/*
    auto biu~
    bg4uvr@2023
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <linux/limits.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <ctype.h>
#include "unp.h"
#include <Python.h>
#include <time.h>
#include <string.h>


char tmpbuf[100];//打印使用
char server_kiss[50], port_kiss[10];//USB声卡接口
char server_aprs[50], port_aprs[10]; //APRS平台TCP接口
char mycall[10];//呼号
char msg[256];//短消息
char mode[5];//程序工作模式
char latitude[20];//经度
char longitude[20];//纬度
char dispersed[10];//数据发送偏移时间
char SYS_REBOOT[5];//系统重启使能
char Elevation_Angle[5];//卫星仰角
char ISS_Timer[2][20];//卫星时间相关字符串
char ISS_Timer_Mark = 0;//卫星时间有效标志
char SATELLITE_NAME[15];//要获取卫星数据的名称
char SEND_MARK = 0;//当前数据发送状态
char GET_ISS_TIMER_ERR_NUM = 0;//获取ISS时间失败次数
u_int32_t ISS_Timer_Start,ISS_Timer_End,Periodical_GET_ISS_Timer = 0;//卫星时间戳
u_int32_t REBOOT_Timer = 0;//计算机重启时间戳
FILE *fp = NULL;// 声明一个文件指针变量 fp，并初始化为 NULL

#define MAXLEN 512


//返回文件名,包含年月日信息
char *filename(void)
{
    static char buf[50]; // 静态数组用于存储文件名
    time_t now = time(NULL); // 获取当前时间
    struct tm *timenow = localtime(&now); // 将时间转换为本地时间结构体
    sprintf(buf, "程序运行日志%04d-%02d-%02d.log", timenow->tm_year + 1900, timenow->tm_mon + 1, timenow->tm_mday); // 格式化字符串到buf变量，生成文件名
    return buf; // 返回文件名字符串
}
char *filename_TRx(void)
{
    static char buf[50]; // 静态数组用于存储文件名
    time_t now = time(NULL); // 获取当前时间
    struct tm *timenow = localtime(&now); // 将时间转换为本地时间结构体
    sprintf(buf, "数据收发日志%04d-%02d-%02d.log", timenow->tm_year + 1900, timenow->tm_mon + 1, timenow->tm_mday); // 格式化字符串到buf变量，生成文件名
    return buf; // 返回文件名字符串
}

//返回当前时间字符串 
char *timestr(void)
{
    static char buf[20]; // 静态数组用于存储时间字符串
    time_t now = time(NULL); // 获取当前时间
    struct tm *timenow = localtime(&now); // 将时间转换为本地时间结构体
    sprintf(buf, "%02d:%02d:%02d", timenow->tm_hour, timenow->tm_min, timenow->tm_sec); // 格式化字符串到buf变量，生成时间字符串
    return buf; // 返回时间字符串
}

//返回当前时间字符串 
char *Header(void)
{
    static char buf[30]; // 静态数组用于存储时间字符串
    char Array[7]={0x42,0x49,0x36,0x50,0x49,0x4A,0x3A};
    time_t now = time(NULL); // 获取当前时间
    struct tm *timenow = localtime(&now); // 将时间转换为本地时间结构体
    buf[0] = '[';
    sprintf(&buf[1],"%04d.%02d.%02d %02d:%02d:%02d",timenow->tm_year + 1900, timenow->tm_mon + 1, timenow->tm_mday, timenow->tm_hour, timenow->tm_min, timenow->tm_sec); // 格式化字符串到buf变量，生成时间字符串
    buf[20] = ']';
    memcpy(&buf[21],Array,7);
    return buf; // 返回时间字符串
}

//返回日志格式当前时间字符串 
char *LOG_Timer(void)
{
    static char buf[30]; // 静态数组用于存储时间字符串
    time_t now = time(NULL); // 获取当前时间
    struct tm *timenow = localtime(&now); // 将时间转换为本地时间结构体
    buf[0] = '[';
    sprintf(&buf[1],"%04d年%02d月%02d日 %02d:%02d:%02d",timenow->tm_year + 1900, timenow->tm_mon + 1, timenow->tm_mday, timenow->tm_hour, timenow->tm_min, timenow->tm_sec); // 格式化字符串到buf变量，生成时间字符串
    buf[27] = ']';

    return buf; // 返回时间字符串
}

//KISS数据解码 
int kissdecode(uint8_t *outbuf, uint8_t *inbuf, uint16_t len)
{
    if (inbuf[0] != 0xc0 || inbuf[1] != 0x00 || inbuf[len - 1] != 0xc0)
    {
        fp = fopen(filename(), "a");// 打开文件以进行追加写入
        sprintf(tmpbuf, "%s[错误]kiss数据帧头与帧尾验证失败(0xc0,0x00 ... 0xc0)。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件
                    
        return -1;
    }
    uint16_t in = 2, out = 0;
    while (in < len - 1)
    {
        if (inbuf[in] != 0xdb)
            outbuf[out++] = inbuf[in++];
        else
        {
            switch (inbuf[in + 1])
            {
            case 0xdc:
                outbuf[out++] == 0xc0;
                break;
            case 0xdd:
                outbuf[out++] == 0xdb;
                break;
            default:
                {
                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "%s[错误]kiss 数据没有 '0xdb,xx'。\n", Header());// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
                    
                    return -1;
                }break;
            }
            in += 2;
        }
    }
    outbuf[out] = 0;
    return (out);
}

//KISS数据编码
int kissencode(uint8_t *outbuf, uint8_t *inbuf, uint16_t len)
{
    uint16_t in = 0, out = 2;
    outbuf[0] = 0xc0;
    outbuf[1] = 0x00;
    while (in < len)
    {
        switch (inbuf[in])
        {
        case 0xc0:
            outbuf[out++] == 0xdb;
            outbuf[out++] == 0xdc;
            break;
        case 0xdb:
            outbuf[out++] == 0xdb;
            outbuf[out++] == 0xdd;
            break;
        default:
            outbuf[out++] = inbuf[in];
            break;
        }
        in++;
    }
    outbuf[out++] = 0xc0;
    return (out);
}

//呼号字符串转换
int uicall2str(uint8_t *outbuf, uint8_t *endflag, uint8_t *inbuf)
{
    uint8_t tmpbuf[10], i;
    memset(tmpbuf, 0, 10);
    memcpy(tmpbuf, inbuf, 6);
    for (i = 0; i < 6; i++)
        tmpbuf[i] >>= 1;
    while (tmpbuf[i - 1] == ' ')
        tmpbuf[--i] = 0;
    uint8_t ssid = ((inbuf[6] >> 1) - '0') & 0x0f;
    if (ssid > 0)
        sprintf(tmpbuf + strlen(tmpbuf), "-%d", ssid);
    if (inbuf[6] & 0x80)
        strcat(tmpbuf, "*");
    strcpy(outbuf, tmpbuf);
    if (inbuf[6] & 0x01)
        *endflag = 1;
    else
        *endflag = 0;
    return strlen(tmpbuf);
}

//AX.25数据解码
int decode(uint8_t *outbuf, uint8_t *inbuf, uint16_t len)
{
    char buf[MAXLEN];
    int16_t uilen = kissdecode(buf, inbuf, len);
    if (uilen < 16)
    {
        fp = fopen(filename(), "a");// 打开文件以进行追加写入
        sprintf(tmpbuf, "%s[错误]uidecode数据长度<16。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件
                
        return -1;
    }
    buf[uilen] = 0;
    char *ax25chk = strstr(buf, "\x03\xf0");
    if (ax25chk == NULL || (ax25chk - buf) % 7 != 0 || (ax25chk - buf < 14) || (ax25chk - buf) > 70)
        return sprintf(outbuf, "not AX.25 format data");
    uint8_t endflag = 0, cnt = 0, sourceflag = 0;
    *outbuf = 0;
    uicall2str(outbuf + strlen(outbuf), &endflag, buf + 7);
    if (outbuf[strlen(outbuf) - 1] == '*')
        outbuf[strlen(outbuf) - 1] = 0;
    sourceflag = endflag;
    strcat(outbuf, ">");
    uicall2str(outbuf + strlen(outbuf), &endflag, buf);
    sprintf(outbuf + strlen(outbuf), ",");
    if (sourceflag == 0)
    {
        while (endflag == 0)
        {
            uicall2str(outbuf + strlen(outbuf), &endflag, buf + cnt * 7 + 14);
            strcat(outbuf, ",");
            if (++cnt > 8)
            {
                fp = fopen(filename(), "a");// 打开文件以进行追加写入
                sprintf(tmpbuf, "%s[错误]未找到UIframe路由EndFlag。\n", Header());// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                fclose(fp);// 关闭文件
        
                return -1;
            }
        }
    }
    uint8_t *laststar = strrchr(outbuf, '*');
    if (laststar != NULL)
    {
        uint8_t i = 0, j = 0, starcnt = 0;
        for (; &outbuf[i] < laststar; i++)
            if (outbuf[i] != '*')
                outbuf[j++] = outbuf[i];
            else
                starcnt++;
        if (starcnt)
        {
            outbuf[j] = 0;
            strcat(outbuf, laststar);
        }
    }
    outbuf[strlen(outbuf) - 1] = ':';
    u_int16_t msglen = uilen - cnt * 7 - 16;
    uint8_t byte, tmpbuf[10];
    for (uint16_t i = 0; i < msglen; i++)
    {
        byte = buf[cnt * 7 + 16 + i];
        if (byte < 0x20 || byte > 0x7e)
            sprintf(tmpbuf, "<0x%02x>", byte);
        else
            sprintf(tmpbuf, "%c", byte);
        strcat(outbuf, tmpbuf);
    }
    return strlen(outbuf);
}

//字符串转换为呼号 
int str2uicall(uint8_t *outbuf, uint8_t *inbuf)
{
    uint8_t i, j, k;
    for (i = 0; i < 11; i++)
    {
        if (inbuf[i] == '>' || inbuf[i] == ',' || inbuf[i] == ':' || inbuf[i] == '*')
            break;
    }
    if (i == 11)
    {
        fp = fopen(filename(), "a");// 打开文件以进行追加写入
        sprintf(tmpbuf, "%s[错误]呼号转换程序: 输入参数 call+ssid+flag 长度综合 > 10。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件
        
        return -1;
    }
    for (j = 0; j < i; j++)
    {
        if (inbuf[j] == '-')
            break;
    }
    if (j > 6)
    {
        fp = fopen(filename(), "a");// 打开文件以进行追加写入
        sprintf(tmpbuf, "%s[错误]呼号转换程序:call长度 > 6。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件

        return -1;
    }
    for (k = 0; k < j; k++)
        outbuf[k] = inbuf[k] << 1;
    while (k < 6)
        outbuf[k++] = 0x40;
    if (j == i)
        outbuf[k] = '0' << 1;
    else
    {
        switch (i - j)
        {
        case 2:
            outbuf[k] = inbuf[j + 1] << 1;
            break;
        case 3:
            outbuf[k] = inbuf[j + 2] + 10 << 1;
            break;
        default:
            {
                fp = fopen(filename(), "a");// 打开文件以进行追加写入
                sprintf(tmpbuf, "%s[错误]呼号转换程序:ssid数据长度错误。\n", Header());// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                fclose(fp);// 关闭文件
            }break;
        }
    }
    if (inbuf[i] == '*')
    {
        outbuf[k] |= 0x80;
        i++;
    }
    if (inbuf[i] == ':')
        outbuf[k] |= 0x01;
    return ++i;
}

//AX.25数据编码
int encode(uint8_t *outbuf, uint8_t *inbuf)
{
    uint8_t buf[MAXLEN];
    memset(buf, 0, sizeof(buf));
    uint16_t ptr = 0;
    uint8_t routecnt = 0;
    ptr += str2uicall(buf + 7, inbuf);
    buf[13] |= 0x80;
    ptr += str2uicall(buf, inbuf + ptr);
    while (!(buf[6] & 0x01 || buf[13 + routecnt * 7] & 0x01))
    {
        ptr += str2uicall(buf + (routecnt + 2) * 7, inbuf + ptr);
        routecnt++;
        if (buf[13 + routecnt * 7] & 0x80)
            for (uint8_t i = 0; i < routecnt; i++)
                buf[13 + i * 7] |= 0x80;
    }
    buf[(routecnt + 2) * 7] = 0x03;
    buf[(routecnt + 2) * 7 + 1] = 0xf0;
    buf[(routecnt + 2) * 7 + 2] = 0;
    sprintf(buf + strlen(buf), "%s", inbuf + ptr);
    return kissencode(outbuf, buf, strlen(buf));
}

//获取卫星轨道倾角参数
double strToDouble(char* str) 
{
    double num = 0.0;
    double fraction = 0.0;
    int sign = 1;
    int i = 0;
 
    // 处理负号
    if (str[0] == '-') {
        sign = -1;
        i++;
    }
 
    // 处理整数部分
    while (str[i] != '\0' && str[i] != '.') {
        num = num * 10 + (str[i] - '0');
        i++;
    }
 
    // 处理小数部分
    if (str[i] == '.') {
        double base = 0.1;
        i++;
        while (str[i] != '\0') {
            fraction = fraction + (str[i] - '0') * base;
            base *= 0.1;
            i++;
        }
    }
    
    return sign * (num + fraction);
}

//字符串转UTC时间
long metis_strptime(char *str_time) 
{
    struct tm tm_time;
    memset(&tm_time, 0, sizeof(struct tm));

    // 解析字符串
    if (strptime(str_time, "%Y-%m-%d %H:%M:%S", &tm_time) == NULL) 
    {
        fp = fopen(filename(), "a");// 打开文件以进行追加写入
        sprintf(tmpbuf, "%s[错误]输入UTC时间字符串格式不正确。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件
        
        fprintf(stderr, "Error parsing time string.\n");
        return -1;
    }

    // 转换为UTC时间
    time_t utc_time = timegm(&tm_time);
    if (utc_time == -1) 
    {
        fp = fopen(filename(), "a");// 打开文件以进行追加写入
        sprintf(tmpbuf, "%s[错误]转换为UTC时出错。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件
    
        fprintf(stderr, "Error converting to UTC.\n");
        return -1;
    }

    return utc_time;
}

//字符串大写转换
char *strupr(char *str)
{
    char *ptr = str;
    while (*ptr != '\0')
    {
        if (islower(*ptr))
            *ptr = toupper(*ptr);
        ptr++;
    }
    return str;
}

//判断参数是否为空
void determine_blank(char *OUT,char *IN)
{
    for (char i=0; i<255; i++)
    {
        if((IN[i] == '\r') || (IN[i] == '\n') || (IN[i] == '\t') || (IN[i] == '\v') || (IN[i] == '\f') || (IN[i] == 0))
        {
            break;
        }
        else 
        {
            OUT[i] = IN[i];
        }
    }
}

void chworkdir()
{
    char exePath[PATH_MAX];
    memset(exePath, 0, sizeof(exePath));
	//读取进程当前执行文件绝对路径,保存至exePath
    readlink("/proc/self/exe", exePath, sizeof(exePath));
    char *exeDir = dirname(exePath);
	//从exePath得到目录路径,保存至exeDir
    chdir(exeDir);//更改当前工作目录至exeDir
}

//重启计算机
void reboot()
{
    //BI6PIJ:完全是无奈之举,因为程序内调用了python程序，导致重复调用时候 很可能是因为在之前调用python程序后产生的线程没有关闭(阻塞问题)，
    //导致的在二次重复调用时程序错误，所以使用系统重启命令/重启线程命令让系统重启后自动又进入ISS时间下载并判断循环。
    //请各路大神看看有没有知道怎么解决的，麻烦把问题原因和解决方法告知下(^-^) 十分感谢: qiuzhichao@126.com

    if(SYS_REBOOT[0] == '1')
    {
        fp = fopen(filename(), "a");// 打开文件以进行追加写入
        sprintf(tmpbuf, "%s[错误]获取ISS时间失败，当前系统执行重启计算机命令。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件

        system("sudo /sbin/reboot");//命令系统重新启动
    }
    else if(SYS_REBOOT[0] == '2')
    {
				fp = fopen(filename(), "a");// 打开文件以进行追加写入
        sprintf(tmpbuf, "%s[错误]获取ISS时间失败，准备重启子线程。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件
		            
				exit(0);// 退出程序，状态码为 0
		}
}

//字符串转数据
char Ascii2HEX(char *Data)
{
    char ret=0;

    for(char i=0;i<3;i++)
    {
        if((Data[i] >= '0') && (Data[i] <= '9'))
        {
            ret *= 10;
            ret += Data[i] - '0';
        }
        else return ret;
    }
    return ret;
}

//检查配置文件
int checkcfg(void)
{
    fp = fopen("autobiu.conf", "r");
    if (fp == NULL)
    {
		//配置文件不存在,创建默认配置文件
        fp = fopen("autobiu.conf", "w");
        fprintf(fp, "# autobiu.conf\n");
        fprintf(fp, "# 遵守业余无线电法律法规，珍惜频谱资源，享受快乐人生!!\n\n");

        fprintf(fp, "# server_kiss 与 port_kiss 参数为接收无线电数据接口,一般不用修改;\n");
        fprintf(fp, "server_kiss:\t127.0.0.1\nport_kiss:\t8001\n\n");
        
        fprintf(fp, "# server_aprs 与 port_aprs 参数为APRS数据交互地址;\n");
        fprintf(fp, "server_aprs:\tasia.aprs2.net\nport_aprs:\t14580\n\n");
        
        fprintf(fp, "# mycall参数为您的呼号注意以‘-6’结尾;\n");
        fprintf(fp, "mycall:\t\tBG4UVR-6\n\n");
        
        fprintf(fp, "# msg参数为数据附带消息,注意不能有空格,请尽可能短一些,越短发射成功率越高;\n");
        fprintf(fp, "msg:\t\t!3445.59N/11337.87E`73_TU_FROM_ZhengZhou_CHINA\n\n");
        
        fprintf(fp, "# mode参数为程序运行版本,0为原始版本，1为当前版本;\n");
        fprintf(fp, "mode:\t\t1\n\n");
        
        fprintf(fp, "# latitude 与 longitude 参数为您所在位置经纬度坐标,注意‘N/S和E/W必须存在不可删除’;\n");
        fprintf(fp, "latitude:\t34.7466N\nlongitude:\t113.6250E\n\n");
        
        fprintf(fp, "# dispersed参数为发送数据偏移延时时间(秒),默认延时0秒,可用来避免与其他距离相近台友冲突;\n");
        fprintf(fp, "dispersed:\t0\n\n");
        
        fprintf(fp, "# Elevation_Angle参数为卫星轨道仰角筛选参数,大于等于这个参数才会被检索到过境数据,否则就会放弃\n");
        fprintf(fp, "# (设置为0.0时就会和手机软件时间对照但是不建议,仰角太低时发射数据没用成功率很低,强烈建议不要低于10.0以下);\n");
        fprintf(fp, "Elevation_Angle:10.0\n\n");

        fprintf(fp, "# SYS_REBOOT参数为获取ISS时间失败重启使能标志,0为关闭,1为自动重启系统,2为自动重启子线程;\n");
        fprintf(fp, "SYS_REBOOT:\t2\n\n");

        fprintf(fp, "# SATELLITE_NAME参数为要跟踪的卫星名称,如ISS空间站为“ISS (ZARYA)”一定要与TLE文件内一致包括空格;\n");
        fprintf(fp, "SATELLITE_NAME:\tISS (ZARYA)\n\n");

        fclose(fp);
        
        fp = fopen(filename(), "a");// 打开文件以进行追加写入
        sprintf(tmpbuf, "%s未找到配置文件 \"autobiu.conf\" , 现在已经自动创建,\n请修改呼号及位置信息后重新运行程序!\n\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        sprintf(tmpbuf, "%s现在程序终止运行。\n\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件
                
        return -1;
    }
    else
    {
        char buf[256];
        uint8_t confno = 0;
        char *head, *tail;
        while (fgets(buf, 256, fp) != NULL)
        {
            if (buf[0] == '#')
                continue;
			 //判断配置项类型并读取
            if (strstr(buf, "server_kiss:"))
                confno = 1;
            else if (strstr(buf, "port_kiss:"))
                confno = 2;
            else if (strstr(buf, "server_aprs:"))
                confno = 3;
            else if (strstr(buf, "port_aprs:"))
                confno = 4;
            else if (strstr(buf, "mycall:"))
                confno = 5;
            else if (strstr(buf, "msg:"))
                confno = 6;
            else if (strstr(buf, "mode:"))
                confno = 7;
            else if (strstr(buf, "latitude:"))
                confno = 8;
            else if (strstr(buf, "longitude:"))
                confno = 9;
            else if (strstr(buf, "dispersed:"))
                confno = 10;
            else if (strstr(buf, "Elevation_Angle:"))
                confno = 11;
            else if (strstr(buf, "SYS_REBOOT:"))
                confno = 12;
            else if (strstr(buf, "SATELLITE_NAME:"))
            		confno = 13;
            else
                continue;
            head = strchr(buf, ':');
            do
                head++;
            while (isspace(*head));//这个判断参数只要遇到空格就不再放了
            tail = head;
            if (confno != 13)
            {
                do
                    tail++;
                while (!isspace(*tail));
            }
            else
            {
                do
                    tail++;
                while (*tail != '\n');
            }
            *tail = 0;
            switch (confno)
            {
            case 1:
                strcpy(server_kiss, head);
                break;
            case 2:
                strcpy(port_kiss, head);
                break;
            case 3:
                strcpy(server_aprs, head);
                break;
            case 4:
                strcpy(port_aprs, head);
                break;
            case 5:
                strcpy(mycall, strupr(head));
                break;
            case 6:
                strcpy(msg, head);
                break;
            case 7:
                strcpy(mode, head);
                break;
            case 8:
                strcpy(latitude, head);
                break;
            case 9:
                strcpy(longitude, head);
                break;
            case 10:
                strcpy(dispersed, head);
                break;
            case 11:
                strcpy(Elevation_Angle, head);
                break;
            case 12:
                strcpy(SYS_REBOOT, head);
                break;
            case 13:
                determine_blank(SATELLITE_NAME, head);
                break;
            }
        }
        fclose(fp);
		//判断必须配置项是否完整 
        if (strlen(server_kiss) && strlen(port_kiss) && 
        	strlen(server_aprs) && strlen(port_aprs) && 
        	strlen(mycall) && strlen(msg) &&
        	strlen(mode) && strlen(latitude) && strlen(longitude) &&
        	strlen(dispersed) && strlen(Elevation_Angle) && strlen(SYS_REBOOT) &&
        	strlen(SATELLITE_NAME)
        	)
        {
            fp = fopen(filename(), "a");// 打开文件以进行追加写入
            sprintf(tmpbuf,"%s配置文件已读取success:\n", Header());
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%sserver_kiss:\t%s\n", Header(),server_kiss);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%sport_kiss:\t\t%s\n", Header(),port_kiss);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%sserver_aprs:\t%s\n", Header(),server_aprs);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%sport_aprs:\t\t%s\n", Header(),port_aprs);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%smycall:\t\t%s\n", Header(),mycall);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%smsg:\t\t%s\n", Header(),msg);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%smode:\t\t%s\n", Header(),mode);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%slatitude:\t\t%s\n", Header(),latitude);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%slongitude:\t\t%s\n", Header(),longitude);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%sdispersed:\t\t%s\n", Header(),dispersed);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%sElevation_Angle:\t%s\n", Header(),Elevation_Angle);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%sSYS_REBOOT:\t\t%s\n", Header(),SYS_REBOOT);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            sprintf(tmpbuf,"%sSATELLITE_NAME:\t%s\n", Header(),SATELLITE_NAME);
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            
            sprintf(tmpbuf,"\n");//结尾为换行
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            fclose(fp);// 关闭文件
            
            return 1;
        }
        else
        {
            fp = fopen(filename(), "a");// 打开文件以进行追加写入
            sprintf(tmpbuf, "%s[错误]'autodiu.confg'错误，请检查程序是否退出！\n", Header());// 格式化字符串到tmpbuf变量
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            fclose(fp);// 关闭文件

            return -1;
        }
    }
}

//获取ISS过境时间数据
int GET_TIMER() 
{
		ISS_Timer_Mark = 0;//先清卫星数据有效标志
		
    fp = fopen(filename(), "a");// 打开文件以进行追加写入

    sprintf(tmpbuf, "%s开始准备执行获取轨道数据python脚本。\n", Header());// 格式化字符串到tmpbuf变量
    printf("%s", tmpbuf);// 打印tmpbuf的内容
    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        
    //删除上次下载的TLE文件
    const char *file_path = "stations.txt";
    if(remove(file_path) == 0)
    {
        sprintf(tmpbuf, "%s已成功删除上次下载的TLE文件。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
    }
    else
    {
        sprintf(tmpbuf, "%s[错误]TLE文件在删除时出错。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
    }

    // 初始化 Python 解释器
    sprintf(tmpbuf, "%s初始化Python解释器。\n", Header());// 格式化字符串到tmpbuf变量
    printf("%s", tmpbuf);// 打印tmpbuf的内容
    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
    Py_Initialize();

    // 添加当前目录到模块搜索路径
    sprintf(tmpbuf, "%s添加python目录到模块搜索路径。\n", Header());// 格式化字符串到tmpbuf变量
    printf("%s", tmpbuf);// 打印tmpbuf的内容
    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append(\".\")");

    // 导入 python_script 模块
    sprintf(tmpbuf, "%s导入python_script模块。\n", Header());// 格式化字符串到tmpbuf变量
    printf("%s", tmpbuf);// 打印tmpbuf的内容
    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
    PyObject* module_name = PyUnicode_DecodeFSDefault("python_script");
    PyObject* module = PyImport_Import(module_name);
    Py_DECREF(module_name);

    if (module != NULL) 
    {
        // 获取 python_function 函数
        sprintf(tmpbuf, "%s获取python_function函数。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        PyObject* function = PyObject_GetAttrString(module, "python_function");
        if (function && PyCallable_Check(function)) 
        {
            // 创建一个包含3个字符串和一个浮点数的元组
            PyObject *pArgs = PyTuple_Pack(4,
                                           PyUnicode_FromString(latitude),
                                           PyUnicode_FromString(longitude),
                                           PyUnicode_FromString(SATELLITE_NAME),
                                           PyFloat_FromDouble(strToDouble(Elevation_Angle)));

            // 调用 python_function 函数
            sprintf(tmpbuf, "%s调用python_function函数。\n", Header());// 格式化字符串到tmpbuf变量
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            PyObject* result = PyObject_CallObject(function, pArgs);
            if (result != NULL) 
            {
                // 处理返回值
                if (PyList_Check(result)) 
                {
                    Py_ssize_t size = PyList_Size(result);
                    sprintf(tmpbuf, "%s获取到python程序返回数据共%zd条。\n", Header(),size);// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    
                    for (Py_ssize_t i = 0; i < size; i++) 
                    {
                        PyObject *item = PyList_GetItem(result, i);
                        if (PyTuple_Check(item) && PyTuple_Size(item) == 2)
                        {
                            PyObject *py_local_time = PyTuple_GetItem(item, 0);
                            PyObject *py_name = PyTuple_GetItem(item, 1);
                            // 将 Python 对象转换为 C 字符串
                            const char *local_time_str = PyUnicode_AsUTF8(py_local_time);
                            const char *name_str = PyUnicode_AsUTF8(py_name);
                            // 输出结果
                            sprintf(tmpbuf, "%spython程序返回数据:%s,事件:%s。\n", Header(),local_time_str, name_str);// 格式化字符串到tmpbuf变量
                            printf("%s", tmpbuf);// 打印tmpbuf的内容
                            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                            if(i == 0)
                            {
                                if(memcmp(name_str,"升起",4) == 0)
                                {
                                    memcpy(ISS_Timer[0],local_time_str,20);//拷贝时间字符串
                                    ISS_Timer_Mark = 0x55;//置卫星时间数据标志为11H
                                }
                            }
                            else if(i == 2)
                            {
                                if((memcmp(name_str,"落下",4) == 0) && (ISS_Timer_Mark == 0x55))
                                {
                                    memcpy(ISS_Timer[1],local_time_str,20);//拷贝时间字符串
                                    ISS_Timer_Mark = 0xAA;//置卫星时间数据标志为有效
                                    //字符串格式
                                    //2024-08-11 08:20:08
                                    ISS_Timer_Start = metis_strptime(ISS_Timer[0]);//更新卫星过境开始时间
                                    ISS_Timer_End = metis_strptime(ISS_Timer[1]);//更新卫星过境结束时间
                                    ISS_Timer_Start -= 8 * 60 * 60;//-时区
                                    ISS_Timer_End -= 8 * 60 * 60;//-时区
                                    
                                    sprintf(tmpbuf, "%s成功获取到最近一次卫星过境开始时间戳:%ld。\n", Header(),ISS_Timer_Start);// 格式化字符串到tmpbuf变量
                                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                                    sprintf(tmpbuf, "%s成功获取到最近一次卫星过境结束时间戳:%ld。\n", Header(),ISS_Timer_End);// 格式化字符串到tmpbuf变量
                                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                                    sprintf(tmpbuf, "%s获取当前系统时间戳:%ld。\n", Header(),time(NULL));// 格式化字符串到tmpbuf变量
                                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                                }
                            }
                        }
                    }
                }
                else
                {
                    sprintf(tmpbuf, "%s[错误]没有获取到所调用到的python返回数据。\n", Header());// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                }
                Py_DECREF(result);

                sprintf(tmpbuf, "%spython函数执行成功。\n", Header());// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            } 
            else 
            {
                sprintf(tmpbuf, "%s[错误]python函数执行错误。\n", Header());// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                PyErr_Print();
            }
            Py_DECREF(function);
        } 
        else 
        {
            if (PyErr_Occurred())
                PyErr_Print();
            sprintf(tmpbuf, "%s[错误]找不到python_function 函数。\n", Header());// 格式化字符串到tmpbuf变量
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        }
        Py_DECREF(module);
    } 
    else 
    {
        PyErr_Print();
        sprintf(tmpbuf, "%s[错误]无法加载python_function 函数。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
    }
    // 关闭 Python 解释器
    sprintf(tmpbuf, "%spython函数调用结束准备关闭解释器。\n", Header());// 格式化字符串到tmpbuf变量
    printf("%s", tmpbuf);// 打印tmpbuf的内容
    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
    Py_Finalize();
    
    fclose(fp);// 关闭文件
    Periodical_GET_ISS_Timer = time(NULL);//更新获取ISS数据时间
}

void Process()
{
    uint8_t buffer[MAXLEN], dspbuf[MAXLEN], callcheck[15], routecheck[15];// 声明一些 uint8_t 类型的数组变量，分别为 buffer、dspbuf、tmpbuf、callcheck、routecheck，其长度分别为 MAXLEN、MAXLEN、100、15、15
    u_int32_t starttime = 0, lasttime = 0;// 声明两个 u_int32_t 类型的变量 starttime 和 lasttime，并初始化为 0
    uint8_t workflag = 0, login = 0;// 声明两个 uint8_t 类型的变量 workflag 和 login，并初始化为 0
    fd_set rset;// 声明一个文件描述符集合变量 rset
    struct timeval tv; // 声明一个 timeval 结构体变量 tv
    int s_fd, i_fd = -1, max_fd, m, n, optval;// 声明一些 int 类型的变量 s_fd、i_fd、max_fd、m、n、optval，并初始化 i_fd 为 -1
    socklen_t optlen = sizeof(optval);// 声明一个 socklen_t 类型的变量 optlen，并初始化为 optval 的大小
    s_fd = Tcp_connect(server_kiss, port_kiss);// 调用 Tcp_connect 函数连接服务器 server_kiss 和端口 port_kiss，并将返回的文件描述符赋值给 s_fd
    i_fd = Tcp_connect(server_aprs, port_aprs); // 调用 Tcp_connect 函数连接服务器 server_aprs 和端口 port_aprs，并将返回的文件描述符赋值给 i_fd
    setsockopt(s_fd, IPPROTO_TCP, TCP_NODELAY, &optval, optval);// 设置 s_fd 文件描述符的 TCP_NODELAY 选项为 optval 的
    setsockopt(i_fd, IPPROTO_TCP, TCP_NODELAY, &optval, optval); // 设置 i_fd 文件描述符的 TCP_NODELAY 选项为 optval 的值
    optval = 1;// 将 optval 设置为 1
    setsockopt(s_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);// 设置 s_fd 文件描述符的 SO_KEEPALIVE 选项为 optval 的值
    setsockopt(i_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);// 设置 i_fd 文件描述符的 SO_KEEPALIVE 选项为 optval 的值
    optval = 3;// 将 optval 设置为 3
    setsockopt(s_fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen);// 设置 s_fd 文件描述符的 TCP_KEEPCNT 选项为 optval 的值
    setsockopt(i_fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen);// 设置 i_fd 文件描述符的 TCP_KEEPCNT 选项为 optval 的值
    optval = 60;// 将 optval 设置为 60
    setsockopt(s_fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen);// 设置 s_fd 文件描述符的 TCP_KEEPIDLE 选项为 optval 的值
    setsockopt(i_fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen);// 设置 i_fd 文件描述符的 TCP_KEEPIDLE 选项为 optval 的值
    optval = 5;// 将 optval 设置为 5
    setsockopt(s_fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen); // 设置 s_fd 文件描述符的 TCP_KEEPINTVL 选项为 optval 的值
    setsockopt(i_fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen);// 设置 i_fd 文件描述符的 TCP_KEEPINTVL 选项为 optval 的值
    fp = fopen(filename(), "a");// 打开文件以进行追加写入
    printf(tmpbuf,"%s开始侦听国际空间站/卫星下发的无线电通讯数据...\n",Header()); // 打印字符串 "monitoring radio kiss data.." 到标准输出
    printf("%s", tmpbuf);// 打印tmpbuf的内容
    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
    fclose(fp);// 关闭文件
    
    while (1)
    {
        FD_ZERO(&rset);
        FD_SET(s_fd, &rset);
        FD_SET(i_fd, &rset);
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        max_fd = max(s_fd, i_fd);
        m = Select(max_fd + 1, &rset, NULL, NULL, &tv);
        if (m > 0)
        {
            if (FD_ISSET(i_fd, &rset))  //来自APRS-IS TCP连接的数据  // 检查 i_fd 文件描述符是否在 rset 文件描述符集合中
            {
                n = recv(i_fd, buffer, MAXLEN, 0);// 从 i_fd 文件描述符接收数据，并将结果存储在 buffer 中，最大长度为 MAXLEN，标志为 0
                if (n == 0)
                {
                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "%s[错误]远程APRS服务器当前未能连接。\n", Header());// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
                    
                    fprintf(stderr, "远程APRS服务器当前未能连接。");// 打印字符串 "remote disconnect" 到标准错误输出
                    exit(0);// 退出程序，状态码为 0
                }
                if ((n < 0) && !(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN))
                {
                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "%s[错误]读取APRS服务器远程错误:%d。\n", Header(),errno);// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
                    
                    fprintf(stderr, "读取APRS服务器远程错误: %d", errno);// 打印字符串 "read from remote error: " 和 errno 的值到标准错误输出
                    exit(0);// 退出程序，状态码为 0
                }
                if (n > 0)
                {
                    if (login == 0 && (strstr(buffer, "aprsc") || strstr(buffer, "javAPRSSrvr")))// 如果尚未登录且接收到的数据中包含 "aprsc" 或 "javAPRSSrvr" 字符串
                    {
						//登录APRS-IS服务器 
                        sprintf(dspbuf, "user %s pass -1 vers autodiu 1.0 filter b/%s\r\n", mycall, mycall);// 格式化字符串并将结果存储在 dspbuf 中
                        Write(i_fd, dspbuf, strlen(dspbuf));// 向 i_fd 文件描述符写入 dspbuf 中的内容，长度为 dspbuf 的长度
                        login = 1;// 设置 login 变量为 1，表示已登录
                    }
                    sprintf(callcheck, "%s>", mycall);// 格式化字符串并将结果存储在 callcheck 中
                    if (workflag == 1 && strstr(buffer, callcheck) && strstr(buffer, "RS0ISS*")) // we only check ISS, ignore other sat.// 如果 workflag 为 1，并且接收到的数据中包含 callcheck 字符串和 "RS0ISS*" 字符串
                    {
						//任务完成,关闭workflag
                        fp = fopen(filename(), "a");// 打开一个文件，并将文件指针赋值给 fp
                        sprintf(tmpbuf, "%s当前发送任务已收到APRS服务器的确认,本次任务结束。\n", Header());// 格式化字符串到tmpbuf变量
                        printf("%s", tmpbuf);// 打印tmpbuf的内容
                        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                        fclose(fp);// 关闭文件
                        
                        workflag = 0;// 设置 workflag 为 0，表示任务完成
                        
                        //BI6PIJ:添加一个简要的LOG文件
                        if(SEND_MARK == 0xAA)//之前有发射任务
                        {
                            fp = fopen(filename_TRx(), "a");// 打开文件以进行追加写入
                            sprintf(tmpbuf, "[成功];\n");// 格式化字符串到tmpbuf变量
                            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                            fclose(fp);// 关闭文件
                        }
                        SEND_MARK = 0;//当前已收到回应
                    }
                }
            }
            if (FD_ISSET(s_fd, &rset))   //来自KISS TCP连接的数据// 检查 s_fd 文件描述符是否在 rset 文件描述符集合中
            {
                n = recv(s_fd, buffer, MAXLEN, 0);// 从 s_fd 文件描述符接收数据，并将结果存储在 buffer 中，最大长度为 MAXLEN，标志为 0
                if (n == 0)
                {
                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "%s[错误]未能与KISS建立连接。\n", Header());// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
        
                    fprintf(stderr, "未能与KISS建立连接。");// 打印字符串 "remote disconnect" 到标准错误输出
                    exit(0);// 退出程序，状态码为 0
                }
                if ((n < 0) && !(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN))
                {
                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "%s[错误]读取KISS远程错误:%d。\n", Header(),errno);// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
                    
                    fprintf(stderr, "读取KISS远程错误: %d", errno);// 打印字符串 "read from remote error: " 和 errno 的值到标准错误输出
                    exit(0);// 退出程序，状态码为 0
                }
                if (n > 0)
                {
                    if (buffer[0] == 0xc0 && buffer[1] == 0x00 && buffer[n - 1] == 0xc0)
                    {
                        fp = fopen(filename(), "a");// 打开一个文件，并将文件指针赋值给 fp
                        sprintf(tmpbuf, "%s收到KISS数据:\n", Header());// 格式化字符串到tmpbuf变量
                        printf("%s", tmpbuf);// 打印 tmpbuf 到标准输出
                        fprintf(fp, "%s", tmpbuf);// 将 tmpbuf 写入文件
                        for (uint16_t i = 0; i < n; i++)
                        {
                            printf("%02X ", buffer[i]);// 打印 buffer[i] 的十六进制表示到标准输出
                            fprintf(fp, "%02X ", buffer[i]);// 将 buffer[i] 的十六进制表示写入文件
                        }
                        printf("\n");
                        fprintf(fp, "\n");
                        decode(dspbuf, buffer, n);// 调用 decode 函数对 buffer 中的数据进行解码，并将解码结果存储在 dspbuf 中
                        printf("%s\n", dspbuf);// 打印 dspbuf 到标准输出
                        fprintf(fp, "%s\n", dspbuf);// 将 dspbuf 写入文件
                        if (workflag == 0 && time(NULL) - lasttime > 900)// 如果 workflag 为 0 并且距离上次任务时间超过 900 秒
                        {
                            if (                       // 检查 dspbuf 中是否包含特定字符串，如果包含则表示接收到 ISS 或卫星的信号
                                strstr(dspbuf, "RS0ISS*") || strstr(dspbuf, "RS0ISS>") ||
                                strstr(dspbuf, "NA1SS*") || strstr(dspbuf, "NA1SS>") ||
                                strstr(dspbuf, "APRSAT*") || strstr(dspbuf, "APRSAT>") ||
                                strstr(dspbuf, "AISAT*") || strstr(dspbuf, "AISAT>") ||
                                strstr(dspbuf, "ARISS*") || strstr(dspbuf, "ARISS>") ||
                                strstr(dspbuf, "PCSAT-1*") || strstr(dspbuf, "PCSAT-1>") ||
                                strstr(dspbuf, "PSAT*") || strstr(dspbuf, "PSAT>") ||
                                strstr(dspbuf, "SGATE*") || strstr(dspbuf, "SGATE>") ||
                                strstr(dspbuf, "A55BTN*") || strstr(dspbuf, "A55BTN>"))
                            {
                                sprintf(tmpbuf, "%s我们成功收到了一条来自ISS国际空间站或卫星的无线电信号,现在开始执行发射任务。\n", Header());// 格式化字符串到tmpbuf变量
                                printf("%s", tmpbuf);// 打印tmpbuf的内容
                                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                                starttime = time(NULL); // 设置 starttime 为当前时间
                                
                                workflag = 1;// 设置 workflag 为 1，表示任务开始
                            }
                        }
                        fclose(fp); // 关闭文件
                        
                        //BI6PIJ:添加一个简要的LOG文件
                        fp = fopen(filename_TRx(), "a");// 打开文件以进行追加写入
                        if(SEND_MARK == 0xAA)//之前有发射任务
                        {
                            sprintf(tmpbuf, "[执行结果被接收抢占];\n");// 格式化字符串到tmpbuf变量
                            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                        }
                        sprintf(tmpbuf, "%s当前我们收到了一条来自APRS空间站的转发信标:%s;\n",LOG_Timer(),dspbuf);// 格式化字符串到tmpbuf变量
                        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                        fclose(fp);// 关闭文件
                        SEND_MARK = 0;//当前已收到回应
                    }
                }
            }
        }
        if (workflag > 0)
        {
			//工作状态,发送定期APRS信标 
            if ((time(NULL) - lasttime) > 30)// 如果当前时间减去上次时间大于30秒
            {
                fp = fopen(filename(), "a");// 打开文件以进行追加写入
                sprintf(dspbuf, "%s>BEACON,ARISS,APRSAT:%s", mycall, msg);// 格式化字符串到dspbuf变量
                n = encode(buffer, dspbuf);// 调用encode函数对buffer进行编码，返回编码后的长度n
                srand(getpid() + time(0));// 使用进程ID和当前时间作为随机数种子
                usleep((rand() % 5000) * 1000);// 使程序休眠随机时间，最多5秒
                Write(s_fd, buffer, n);// 将buffer中的数据写入s_fd文件描述符
                lasttime = time(NULL);// 更新lasttime为当前时间
                
                sprintf(tmpbuf, "%s%s\n", Header(),dspbuf);// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                sprintf(tmpbuf, "%s我们的信标已经向外发送过一次。\n", Header());// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                fclose(fp);// 关闭文件
                
                //BI6PIJ:添加一个简要的LOG文件
                fp = fopen(filename_TRx(), "a");// 打开文件以进行追加写入
                if(SEND_MARK == 0xAA)//之前有发射任务
                {
                    sprintf(tmpbuf, "[失败];\n");// 格式化字符串到tmpbuf变量
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                }
                sprintf(tmpbuf, "%s当前我们已向APRS空间站中继发射了一次信标",LOG_Timer());// 格式化字符串到tmpbuf变量
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                SEND_MARK = 0xAA;//当前已发射等待回应
                fclose(fp);// 关闭文件
            }
            if ((time(NULL) - starttime) > 480)// 如果当前时间减去开始时间大于480秒
            {
                //超时,关闭workflag
                fp = fopen(filename(), "a");// 打开文件以进行追加写入
                sprintf(tmpbuf, "%s发送任务时间超时，本次任务停止。\n", Header());// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                fclose(fp);// 关闭文件
                
                workflag = 0;// 设置workflag为0，表示任务停止
                
                //BI6PIJ:添加一个简要的LOG文件
                if(SEND_MARK == 0xAA)//之前有发射任务
                {
                    fp = fopen(filename_TRx(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "[失败];\n");// 格式化字符串到tmpbuf变量
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
                }
                SEND_MARK = 0;//当前任务已结束
            }
        }
        else if((time(NULL) - Periodical_GET_ISS_Timer) > (24 * 60 * 60))// 如果当前时间减去开始时间大于24小时
        {
        		checkcfg();//更新配置项
        		Periodical_GET_ISS_Timer = time(NULL);//更新获取ISS数据时间
        		if(mode[0] != '0')//当前真正的工作模式不为基础模式
						{
		            GET_TIMER();//获取卫星最新数据
		            if(ISS_Timer_Mark == 0xAA)//获取卫星数据成功
		            {
		                GET_ISS_TIMER_ERR_NUM = 0;//获取数据成功就清失败次数

		                fp = fopen(filename(), "a");// 打开文件以进行追加写入
		                sprintf(tmpbuf, "%s基础模式下自动获取ISS时间成功了,当前模式切换回定时发送模式。\n", Header());// 格式化字符串到tmpbuf变量
		                printf("%s", tmpbuf);// 打印tmpbuf的内容
		                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
		                fclose(fp);// 关闭文件
		                
		                exit(0);// 退出程序，状态码为 0
		            }
		            else 
		            {
		            		GET_ISS_TIMER_ERR_NUM++;
		                if(GET_ISS_TIMER_ERR_NUM >= 3)//获取时间失败次数大于3次就用原始程序
		                {
		                		GET_ISS_TIMER_ERR_NUM = 0;
		                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
		                    sprintf(tmpbuf, "%s[错误]自动获取ISS时间失败次数超过3次,现在重新启动子线程。\n", Header());// 格式化字符串到tmpbuf变量
		                    printf("%s", tmpbuf);// 打印tmpbuf的内容
		                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
		                    fclose(fp);// 关闭文件
		                    
		                    mode[0] = '0';
		                    exit(0);// 退出程序，状态码为 0
		                }
		            }
						}
        }
    }
    close(s_fd);
    close(i_fd);
}

//主要函数
void Periodical_Process()
{
    uint8_t buffer[MAXLEN], dspbuf[MAXLEN], callcheck[15], routecheck[15];// 声明一些 uint8_t 类型的数组变量，分别为 buffer、dspbuf、tmpbuf、callcheck、routecheck，其长度分别为 MAXLEN、MAXLEN、100、15、15
    u_int32_t starttime = 0, lasttime = 0;// 声明两个 u_int32_t 类型的变量 starttime 和 lasttime，并初始化为 0
    uint8_t workflag = 0, login = 0;// 声明两个 uint8_t 类型的变量 workflag 和 login，并初始化为 0
    fd_set rset;// 声明一个文件描述符集合变量 rset
    struct timeval tv; // 声明一个 timeval 结构体变量 tv
    int s_fd, i_fd = -1, max_fd, m, n, optval;// 声明一些 int 类型的变量 s_fd、i_fd、max_fd、m、n、optval，并初始化 i_fd 为 -1
    socklen_t optlen = sizeof(optval);// 声明一个 socklen_t 类型的变量 optlen，并初始化为 optval 的大小
    s_fd = Tcp_connect(server_kiss, port_kiss);// 调用 Tcp_connect 函数连接服务器 server_kiss 和端口 port_kiss，并将返回的文件描述符赋值给 s_fd
    i_fd = Tcp_connect(server_aprs, port_aprs); // 调用 Tcp_connect 函数连接服务器 server_aprs 和端口 port_aprs，并将返回的文件描述符赋值给 i_fd
    setsockopt(s_fd, IPPROTO_TCP, TCP_NODELAY, &optval, optval);// 设置 s_fd 文件描述符的 TCP_NODELAY 选项为 optval 的
    setsockopt(i_fd, IPPROTO_TCP, TCP_NODELAY, &optval, optval); // 设置 i_fd 文件描述符的 TCP_NODELAY 选项为 optval 的值
    optval = 1;// 将 optval 设置为 1
    setsockopt(s_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);// 设置 s_fd 文件描述符的 SO_KEEPALIVE 选项为 optval 的值
    setsockopt(i_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);// 设置 i_fd 文件描述符的 SO_KEEPALIVE 选项为 optval 的值
    optval = 3;// 将 optval 设置为 3
    setsockopt(s_fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen);// 设置 s_fd 文件描述符的 TCP_KEEPCNT 选项为 optval 的值
    setsockopt(i_fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen);// 设置 i_fd 文件描述符的 TCP_KEEPCNT 选项为 optval 的值
    optval = 60;// 将 optval 设置为 60
    setsockopt(s_fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen);// 设置 s_fd 文件描述符的 TCP_KEEPIDLE 选项为 optval 的值
    setsockopt(i_fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen);// 设置 i_fd 文件描述符的 TCP_KEEPIDLE 选项为 optval 的值
    optval = 5;// 将 optval 设置为 5
    setsockopt(s_fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen); // 设置 s_fd 文件描述符的 TCP_KEEPINTVL 选项为 optval 的值
    setsockopt(i_fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen);// 设置 i_fd 文件描述符的 TCP_KEEPINTVL 选项为 optval 的值
    
    fp = fopen(filename(), "a");// 打开文件以进行追加写入
    sprintf(tmpbuf, "%s开始定期更新卫星轨道数据并在卫星过境时发送数据...\n", Header());// 格式化字符串到tmpbuf变量
    printf("%s", tmpbuf);// 打印tmpbuf的内容
    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
    fclose(fp);// 关闭文件

    while (1)
    {
        FD_ZERO(&rset);
        FD_SET(s_fd, &rset);
        FD_SET(i_fd, &rset);
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        max_fd = max(s_fd, i_fd);
        m = Select(max_fd + 1, &rset, NULL, NULL, &tv);
        if (m > 0)
        {
            if (FD_ISSET(i_fd, &rset))  //来自APRS-IS TCP连接的数据  // 检查 i_fd 文件描述符是否在 rset 文件描述符集合中
            {
                n = recv(i_fd, buffer, MAXLEN, 0);// 从 i_fd 文件描述符接收数据，并将结果存储在 buffer 中，最大长度为 MAXLEN，标志为 0
                if (n == 0)
                {
                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "%s[错误]远程APRS服务器当前未能连接。\n", Header());// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
                    
                    fprintf(stderr, "远程APRS服务器当前未能连接。");// 打印字符串 "remote disconnect" 到标准错误输出
                    exit(0);// 退出程序，状态码为 0
                }
                if ((n < 0) && !(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN))
                {
                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "%s[错误]读取APRS服务器远程错误:%d。\n", Header(),errno);// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
                    
                    fprintf(stderr, "读取APRS服务器远程错误: %d", errno);// 打印字符串 "read from remote error: " 和 errno 的值到标准错误输出
                    exit(0);// 退出程序，状态码为 0
                }
                if (n > 0)
                {
                    if (login == 0 && (strstr(buffer, "aprsc") || strstr(buffer, "javAPRSSrvr")))// 如果尚未登录且接收到的数据中包含 "aprsc" 或 "javAPRSSrvr" 字符串
                    {
						//登录APRS-IS服务器 
                        sprintf(dspbuf, "user %s pass -1 vers autodiu 1.0 filter b/%s\r\n", mycall, mycall);// 格式化字符串并将结果存储在 dspbuf 中
                        Write(i_fd, dspbuf, strlen(dspbuf));// 向 i_fd 文件描述符写入 dspbuf 中的内容，长度为 dspbuf 的长度
                        login = 1;// 设置 login 变量为 1，表示已登录
                    }
                    sprintf(callcheck, "%s>", mycall);// 格式化字符串并将结果存储在 callcheck 中
                    if (workflag == 1 && strstr(buffer, callcheck) && strstr(buffer, "RS0ISS*")) // we only check ISS, ignore other sat.// 如果 workflag 为 1，并且接收到的数据中包含 callcheck 字符串和 "RS0ISS*" 字符串
                    {
						//任务完成,关闭workflag
                        fp = fopen(filename(), "a");// 打开一个文件，并将文件指针赋值给 fp
                        sprintf(tmpbuf, "%s当前发送任务已收到APRS服务器的确认,本次任务结束。\n", Header());// 格式化字符串到tmpbuf变量
                        printf("%s", tmpbuf);// 打印tmpbuf的内容
                        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                        fclose(fp);// 关闭文件
                        
                        workflag = 0;// 设置 workflag 为 0，表示任务完成

                        //BI6PIJ:添加一个简要的LOG文件
                        if(SEND_MARK == 0xAA)//之前有发射任务
                        {
                            fp = fopen(filename_TRx(), "a");// 打开文件以进行追加写入
                            sprintf(tmpbuf, "[成功];\n");// 格式化字符串到tmpbuf变量
                            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                            fclose(fp);// 关闭文件
                        }
                        SEND_MARK = 0;//当前已收到回应
                        
                        GET_TIMER();//获取卫星最新数据
                        if(ISS_Timer_Mark != 0xAA)
                        {
                            GET_ISS_TIMER_ERR_NUM++;//获取时间失败次数+1
                            if((SYS_REBOOT[0] == '1') || (SYS_REBOOT[0] == '2'))
                            {
                                REBOOT_Timer = time(NULL);//获取当前时间,10分钟后重启计算机
                            }
                            if(GET_ISS_TIMER_ERR_NUM >= 3)//获取时间失败次数大于3次就用原始程序
                            {
                            		GET_ISS_TIMER_ERR_NUM = 0;
                                fp = fopen(filename(), "a");// 打开文件以进行追加写入
                                sprintf(tmpbuf, "%s[错误]自动获取ISS时间失败次数超过3次,现在切换至基础版本运行。\n", Header());// 格式化字符串到tmpbuf变量
                                printf("%s", tmpbuf);// 打印tmpbuf的内容
                                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                                fclose(fp);// 关闭文件

                                mode[0] = '0';
                                exit(0);// 退出程序，状态码为 0
                            }
                        }
                        else GET_ISS_TIMER_ERR_NUM = 0;//获取数据成功
                    }
                }
            }
            if (FD_ISSET(s_fd, &rset))   //来自KISS TCP连接的数据// 检查 s_fd 文件描述符是否在 rset 文件描述符集合中
            {
                n = recv(s_fd, buffer, MAXLEN, 0);// 从 s_fd 文件描述符接收数据，并将结果存储在 buffer 中，最大长度为 MAXLEN，标志为 0
                if (n == 0)
                {
                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "%s[错误]未能与KISS建立连接。\n", Header());// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
        
                    fprintf(stderr, "未能与KISS建立连接。");// 打印字符串 "remote disconnect" 到标准错误输出
                    exit(0);// 退出程序，状态码为 0
                }
                if ((n < 0) && !(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN))
                {
                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "%s[错误]读取KISS远程错误:%d。\n", Header(),errno);// 格式化字符串到tmpbuf变量
                    printf("%s", tmpbuf);// 打印tmpbuf的内容
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
                    
                    fprintf(stderr, "读取KISS远程错误: %d", errno);// 打印字符串 "read from remote error: " 和 errno 的值到标准错误输出
                    exit(0);// 退出程序，状态码为 0
                }
                if (n > 0)
                {
                    if (buffer[0] == 0xc0 && buffer[1] == 0x00 && buffer[n - 1] == 0xc0)
                    {
                        fp = fopen(filename(), "a");// 打开文件以进行追加写入
                        sprintf(tmpbuf, "%s收到KISS数据:\n", Header());// 格式化字符串到tmpbuf变量
                        printf("%s", tmpbuf);// 打印tmpbuf的内容
                        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                        for (uint16_t i = 0; i < n; i++)
                        {
                            printf("%02X ", buffer[i]);// 打印 buffer[i] 的十六进制表示到标准输出
                            fprintf(fp, "%02X ", buffer[i]);// 将 buffer[i] 的十六进制表示写入文件
                        }
                        printf("\n");
                        fprintf(fp, "\n");
                        decode(dspbuf, buffer, n);// 调用 decode 函数对 buffer 中的数据进行解码，并将解码结果存储在 dspbuf 中
                        printf("%s\n", dspbuf);// 打印 dspbuf 到标准输出
                        fprintf(fp, "%s\n", dspbuf);// 将 dspbuf 写入文件
                        if (workflag == 0 && time(NULL) - lasttime > 900)// 如果 workflag 为 0 并且距离上次任务时间超过 900 秒
                        {
                            if (                       // 检查 dspbuf 中是否包含特定字符串，如果包含则表示接收到 ISS 或卫星的信号
                                strstr(dspbuf, "RS0ISS*") || strstr(dspbuf, "RS0ISS>") ||
                                strstr(dspbuf, "NA1SS*") || strstr(dspbuf, "NA1SS>") ||
                                strstr(dspbuf, "APRSAT*") || strstr(dspbuf, "APRSAT>") ||
                                strstr(dspbuf, "AISAT*") || strstr(dspbuf, "AISAT>") ||
                                strstr(dspbuf, "ARISS*") || strstr(dspbuf, "ARISS>") ||
                                strstr(dspbuf, "PCSAT-1*") || strstr(dspbuf, "PCSAT-1>") ||
                                strstr(dspbuf, "PSAT*") || strstr(dspbuf, "PSAT>") ||
                                strstr(dspbuf, "SGATE*") || strstr(dspbuf, "SGATE>") ||
                                strstr(dspbuf, "A55BTN*") || strstr(dspbuf, "A55BTN>"))
                            {
                                sprintf(tmpbuf, "%s我们成功收到了一条来自ISS国际空间站或卫星的无线电信号。\n", Header());// 格式化字符串到tmpbuf变量
                                printf("%s", tmpbuf);// 打印tmpbuf的内容
                                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                                starttime = time(NULL); // 设置 starttime 为当前时间
                                
                                //workflag = 1;// 设置 workflag 为 1，表示任务开始  //BI6PIJ:接受的数据只记录不再作为启动标记
                            }
                        }
                        fclose(fp); // 关闭文件

                        //BI6PIJ:添加一个简要的LOG文件
                        fp = fopen(filename_TRx(), "a");// 打开文件以进行追加写入
                        if(SEND_MARK == 0xAA)//之前有发射任务
                        {
                            sprintf(tmpbuf, "[执行结果被接收抢占];\n");// 格式化字符串到tmpbuf变量
                            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                        }
                        sprintf(tmpbuf, "%s当前我们收到了一条来自APRS空间站的转发信标:%s;\n",LOG_Timer(),dspbuf);// 格式化字符串到tmpbuf变量
                        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                        fclose(fp);// 关闭文件
                        SEND_MARK = 0;//当前已收到回应
                    }
                }
            }
        }
        if((time(NULL) - Periodical_GET_ISS_Timer) > (4 * 60 * 60))// 如果当前时间减去开始时间大于4小时
        {
        		if((ISS_Timer_Mark != 0xAA) ||
        			((ISS_Timer_Mark == 0xAA) && ((time(NULL) - ISS_Timer_Start) > 15 * 60)))//当前卫星数据无效 或 数据有效且距离开始时间大于15分钟
        		{
		            GET_TIMER();//获取卫星最新数据
		            if(ISS_Timer_Mark != 0xAA)
		            {
		                GET_ISS_TIMER_ERR_NUM++;//获取时间失败次数+1
		                if((SYS_REBOOT[0] == '1') || (SYS_REBOOT[0] == '2'))
		                {
		                    REBOOT_Timer = time(NULL);//获取当前时间,10分钟后重启计算机
		                }
		                if(GET_ISS_TIMER_ERR_NUM >= 3)//获取时间失败次数大于3次就用原始程序
		                {
		                		GET_ISS_TIMER_ERR_NUM = 0;
		                    fp = fopen(filename(), "a");// 打开文件以进行追加写入
		                    sprintf(tmpbuf, "%s[错误]自动获取ISS时间失败次数超过3次,现在切换至基础版本运行。\n", Header());// 格式化字符串到tmpbuf变量
		                    printf("%s", tmpbuf);// 打印tmpbuf的内容
		                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
		                    fclose(fp);// 关闭文件
		                    
		                    mode[0] = '0';
		                    exit(0);// 退出程序，状态码为 0
		                }
		            }
		            else GET_ISS_TIMER_ERR_NUM = 0;//获取数据成功
		        }
        }
        if(ISS_Timer_Mark == 0xAA)//卫星数据有效,将时间字符串转为UTC时间并判断是否已经处于卫星过境状态
        {
            if(time(NULL) >= ISS_Timer_Start)//当前时间已超过开始过境时间
            {
                starttime = time(NULL); // 设置 starttime 为当前时间
                workflag = 1;// 设置 workflag 为 1，表示任务开始
                SEND_MARK = 0;//当前任务开始清发射状态
                ISS_Timer_Mark = 0;//清卫星过境时间有效标志

                fp = fopen(filename(), "a");// 打开文件以进行追加写入
                sprintf(tmpbuf, "%s当前时间到达过境开始时间了,任务开始执行。\n", Header());// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                fclose(fp);// 关闭文件
            }
        }
        if (workflag > 0)
        {
			//工作状态,发送定期APRS信标 
            if ((time(NULL) - lasttime) > (30 + Ascii2HEX(dispersed)))// 如果当前时间减去上次时间大于30秒
            {
                fp = fopen(filename(), "a");// 打开文件以进行追加写入
                sprintf(dspbuf, "%s>BEACON,ARISS,APRSAT:%s", mycall, msg);// 格式化字符串到dspbuf变量
                n = encode(buffer, dspbuf);// 调用encode函数对buffer进行编码，返回编码后的长度n
                srand(getpid() + time(0));// 使用进程ID和当前时间作为随机数种子
                usleep((rand() % 5000) * 1000);// 使程序休眠随机时间，最多5秒
                Write(s_fd, buffer, n);// 将buffer中的数据写入s_fd文件描述符
                lasttime = time(NULL);// 更新lasttime为当前时间
                
                sprintf(tmpbuf, "%s%s\n", Header(),dspbuf);// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                sprintf(tmpbuf, "%s我们的信标已经向外发送过一次。\n", Header());// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                fclose(fp);// 关闭文件
                
                //BI6PIJ:添加一个简要的LOG文件
                fp = fopen(filename_TRx(), "a");// 打开文件以进行追加写入
                if(SEND_MARK == 0xAA)//之前有发射任务
                {
                    sprintf(tmpbuf, "[失败];\n");// 格式化字符串到tmpbuf变量
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                }
                sprintf(tmpbuf, "%s当前我们已向APRS空间站中继发射了一次信标",LOG_Timer());// 格式化字符串到tmpbuf变量
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                SEND_MARK = 0xAA;//当前已发射等待回应
                fclose(fp);// 关闭文件
            }
            if (((time(NULL) - starttime) > 480) || (time(NULL) >= ISS_Timer_End))// 如果当前时间减去开始时间大于480秒 或 超过卫星落下时间
            {
                //超时,关闭workflag
                fp = fopen(filename(), "a");// 打开文件以进行追加写入
                sprintf(tmpbuf, "%s发送任务时间超时，本次任务停止。\n", Header());// 格式化字符串到tmpbuf变量
                printf("%s", tmpbuf);// 打印tmpbuf的内容
                fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                fclose(fp);// 关闭文件
                
                workflag = 0;// 设置workflag为0，表示任务停止

                //BI6PIJ:添加一个简要的LOG文件
                if(SEND_MARK == 0xAA)//之前有发射任务
                {
                    fp = fopen(filename_TRx(), "a");// 打开文件以进行追加写入
                    sprintf(tmpbuf, "[失败];\n");// 格式化字符串到tmpbuf变量
                    fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                    fclose(fp);// 关闭文件
                }
                SEND_MARK = 0;//当前任务已结束

                GET_TIMER();//获取卫星最新数据,需要更新下次过境时间
                if(ISS_Timer_Mark != 0xAA)
                {
                    GET_ISS_TIMER_ERR_NUM++;//获取时间失败次数+1
                    if((SYS_REBOOT[0] == '1') || (SYS_REBOOT[0] == '2'))
                    {
                        REBOOT_Timer = time(NULL);//获取当前时间,10分钟后重启计算机
                    }
                    if(GET_ISS_TIMER_ERR_NUM >= 3)//获取时间失败次数大于3次就用原始程序
                    {
                    		GET_ISS_TIMER_ERR_NUM = 0;
                        fp = fopen(filename(), "a");// 打开文件以进行追加写入
                        sprintf(tmpbuf, "%s[错误]自动获取ISS时间失败次数超过3次,现在切换至基础版本运行。\n", Header());// 格式化字符串到tmpbuf变量
                        printf("%s", tmpbuf);// 打印tmpbuf的内容
                        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
                        fclose(fp);// 关闭文件

                        mode[0] = '0';
                        exit(0);// 退出程序，状态码为 0
                    }
                }
                else GET_ISS_TIMER_ERR_NUM = 0;//获取数据成功
            }
        }
        else if(REBOOT_Timer != 0)
        {
            if(((time(NULL) - REBOOT_Timer) > (10 * 60)) &&
                ((time(NULL) - REBOOT_Timer) < (11 * 60)))// 如果当前时间减去需要重启时间大于10分钟就重启计算机
            {
                //重启计算机
                reboot();
            }
        }
    }
    close(s_fd);
    close(i_fd);
}

int main(int argc, char *argv[])
{
    int ret = system("echo $(pgrep autobiu) |grep -c \" \" > /dev/null");// 执行shell命令检查是否已经有相同程序运行
    if (!ret)
    {
        printf("\n%s程序已在运行，不能运行多次。\n",Header());// 程序已经在运行，无法再次运行
        return -1;// 返回-1表示程序已经在运行，无法再次运行
    }

    printf("\n\t\t--------------\n\t\t|  AUTO BIU  |\n\t\t--------------\n");
    printf("\t\t\t by bg4uvr@qq.com\n");
    printf("\n\t\t------------------------------------------------------\n");
    printf("\n\t\t修改历史:\n");
    printf("\n\t\t------------------------------------------------------\n");
    printf("\n\t\t修改时间:2024-08-01\n");
    printf("\n\t\t修改人:BI6PIJ/BH6IDD  Email:qiuzhichao@126.com\n");
    printf("\n\t\t修改内容:\n");
    printf("\n\t\t1.在原有AUTOBIU基础上增加定时通过互联网获取ISS空间站过境时间,并根据过境时间进行数据发送；\n");
    printf("\n\t\t2.增加卫星轨道数据文件自动更新功能,最久间隔4个小时更新一次,每次卫星过境结束必更新一次为下一次过境做准备。\n");
    printf("\n\t\t3.增加偏移数据发送功能避免干扰，相互间隔时间为0秒起步可自行调整；\n");
    printf("\n\t\t4.调整打印输出信息,增加中文输出。\n");
    printf("\n\t\t5.增加工作模式选择功能,可选择启动原版AUTOBIU程序或单独定时发送程序，默认为定时发送模式;\n");
    printf("\n\t\t6.修改程序运行日志格式,并增加单独无线收发记录文件方便查阅。\n");
    printf("\n\t\t7.鸣谢AUTOBIU原作者BG4UVR。\n");
    printf("\n\t\t------------------------------------------------------\n");
    printf("\n%s你可以输入'./autobiu -d'命令，以调试模式运行程序。\n\n",Header());
    int debug = 0;//调试模式标志，默认为0
    if (argc == 2 && strcmp(argv[1], "-d") == 0)
        debug = 1;//如果命令行参数为"-d"
    else if (argc != 1)
    {
        printf("\n%s命令选项错误，只能使用'-d'。\n\n",Header());// 命令选项错误，只能使用"-d"
        printf("\n%s现在程序终止运行。\n\n",Header());
        return -1;// 返回-1表示程序退出
    }
    chworkdir();// 切换工作目录
    if (checkcfg() < 0)
        return -1;// 检查配置文件，如果失败则返回-1
    if (debug == 0)
    {
        printf("\n%s程序现在以守护进程模式运行（在后台），现在您可以安全注销或断开SSH连接。\n\n",Header());
        printf("\n%s如果你想阻止它，请使用命令：“pkill autobiu”。\n\n",Header());
        daemon_init(argv[0], LOG_DAEMON);// 将程序设置为守护进程
        while (1)
        {
            int pid;
            pid = fork();
            if (pid == 0)
                break;// 在子进程中跳出循环
            else if (pid == -1)
                exit(0);// fork失败，退出程序
            else
            {
                wait(NULL);// 等待子进程结束
            }
            sleep(2);// 休眠2秒
        }
    }
    
    fp = fopen(filename(), "a");// 打开文件以进行追加写入
    if(mode[0] == '0')
    {
        sprintf(tmpbuf, "%s程序启动,开始运行基础版本程序。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件
        
        Process();// 处理主要逻辑
    }
    else if(mode[0] == '1')
    {
        sprintf(tmpbuf, "%s程序启动,开始运行当前版本程序。\n", Header());// 格式化字符串到tmpbuf变量
        printf("%s", tmpbuf);// 打印tmpbuf的内容
        fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
        fclose(fp);// 关闭文件
        
        if(SYS_REBOOT[0] == '1')//系统重启模式为自动重启
        {
            fp = fopen(filename(), "a");// 打开文件以进行追加写入
            sprintf(tmpbuf, "%s休眠20秒等待系统环境启动完成。\n", Header());// 格式化字符串到tmpbuf变量
            printf("%s", tmpbuf);// 打印tmpbuf的内容
            fprintf(fp, "%s", tmpbuf);// 将tmpbuf的内容写入文件
            fclose(fp);// 关闭文件

            sleep(20);// 休眠20秒
        }
        REBOOT_Timer = 0;//清重启计时
        GET_TIMER();//获取卫星最新数据
        Periodical_Process();// 处理主要逻辑
    }
    return (0);// 返回0表示程序正常退出
}


